package com.luhuiguo.cms.server.service.impl;

import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnit;
import javax.persistence.Query;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.luhuiguo.cms.server.entity.Article;
import com.luhuiguo.cms.server.service.ArticleService;
import com.luhuiguo.cms.server.service.AttachmentService;
import com.luhuiguo.cms.server.service.restriction.ArticleFilter;
import com.luhuiguo.cms.server.util.SecurityUtils;
import com.luhuiguo.cms.shared.model.ArticleModel;

@Service
// @Transactional
public class ArticleServiceImpl implements ArticleService {

    @PersistenceUnit
    private EntityManagerFactory emf;

    @Autowired
    private AttachmentService attachmentService;

    // @PersistenceContext
    // private EntityManager em;

    @Override
    public Article getArticle(Long id) {
        EntityManager em = emf.createEntityManager();
        try {
            return em.find(Article.class, id);
        } finally {
            em.close();
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<Article> findArticles() {
        EntityManager em = emf.createEntityManager();
        try {
            Query q = em.createQuery("SELECT t FROM Article t ORDER BY t.lastModified desc");
            List<Article> list = q.getResultList();
            list.size();
            return list;
        } finally {
            em.close();
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<Article> findArticlesByChannelId(Long channelId, int... rowStartIdxAndCount) {
        EntityManager em = emf.createEntityManager();
        try {
            Query q = em
                    .createQuery("SELECT t FROM Article t WHERE t.channelId = :channelId ORDER BY t.rank DESC,t.lastModified desc");
            q.setParameter("channelId", channelId);

            if (rowStartIdxAndCount != null && rowStartIdxAndCount.length > 0) {
                int rowStartIdx = Math.max(0, rowStartIdxAndCount[0]);
                if (rowStartIdx > 0) {
                    q.setFirstResult(rowStartIdx);
                }
                if (rowStartIdxAndCount.length > 1) {
                    int rowCount = Math.max(0, rowStartIdxAndCount[1]);
                    if (rowCount > 0) {
                        q.setMaxResults(rowCount);
                    }
                }
            }
            List<Article> list = q.getResultList();
            list.size();

            return list;
        } finally {
            em.close();
        }
    }

    @Override
    public void saveArticle(Article article) {
        EntityManager em = emf.createEntityManager();
        try {
            article.setCreated(new Date());
            article.setCreatedBy(SecurityUtils.getCurrentUsername());
            article.setLastModified(article.getCreated());
            article.setLastModifiedBy(article.getCreatedBy());
            em.persist(article);
        } finally {
            em.close();
        }

    }

    @Override
    public Article updateArticle(Article article) {
        EntityManager em = emf.createEntityManager();
        try {
            article.setLastModified(new Date());
            article.setLastModifiedBy(SecurityUtils.getCurrentUsername());
            return em.merge(article);
        } finally {
            em.close();
        }
    }

    @Override
    public void deleteArticle(Long id) {
        attachmentService.deleteAttachmentByArticleId(id);
        EntityManager em = emf.createEntityManager();
        try {
            em.remove(em.find(Article.class, id));
        } finally {
            em.close();
        }
    }

    @Override
    public int getArticleCountByChannelId(Long channelId) {
        EntityManager em = emf.createEntityManager();
        try {
            Query q = em.createQuery("SELECT COUNT(t) FROM Article t WHERE t.channelId = :channelId");
            q.setParameter("channelId", channelId);

            return (Integer) q.getSingleResult();
        } finally {
            em.close();
        }
    }

    @Override
    public void deleteArticleByChannelId(Long channelId) {
        List<Article> list = findArticlesByChannelId(channelId);
        for (Article item : list) {
            deleteArticle(item.getId());

        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<Article> findArticlesByStatus(int status, int... rowStartIdxAndCount) {
        EntityManager em = emf.createEntityManager();
        try {
            Query q = em.createQuery("SELECT t FROM Article t WHERE t.status = :status ORDER BY t.lastModified desc");
            q.setParameter("status", status);

            if (rowStartIdxAndCount != null && rowStartIdxAndCount.length > 0) {
                int rowStartIdx = Math.max(0, rowStartIdxAndCount[0]);
                if (rowStartIdx > 0) {
                    q.setFirstResult(rowStartIdx);
                }
                if (rowStartIdxAndCount.length > 1) {
                    int rowCount = Math.max(0, rowStartIdxAndCount[1]);
                    if (rowCount > 0) {
                        q.setMaxResults(rowCount);
                    }
                }
            }
            List<Article> list = q.getResultList();
            list.size();

            return list;
        } finally {
            em.close();
        }

    }

    @Override
    public int getArticleCountByStatus(int status) {
        EntityManager em = emf.createEntityManager();
        try {
            Query q = em.createQuery("SELECT COUNT(t) FROM Article t WHERE t.status = :status");
            q.setParameter("status", status);

            return (Integer) q.getSingleResult();
        } finally {
            em.close();
        }

    }

    @SuppressWarnings("unchecked")
    @Override
    public List<Article> findApprovedArticlesByChannelId(Long channelId, int... rowStartIdxAndCount) {
        EntityManager em = emf.createEntityManager();
        try {
            Query q = em
                    .createQuery("SELECT t FROM Article t WHERE t.channelId = :channelId AND t.status = :status ORDER BY t.lastModified desc");
            q.setParameter("channelId", channelId);
            q.setParameter("status", ArticleModel.APPROVED);

            if (rowStartIdxAndCount != null && rowStartIdxAndCount.length > 0) {
                int rowStartIdx = Math.max(0, rowStartIdxAndCount[0]);
                if (rowStartIdx > 0) {
                    q.setFirstResult(rowStartIdx);
                }
                if (rowStartIdxAndCount.length > 1) {
                    int rowCount = Math.max(0, rowStartIdxAndCount[1]);
                    if (rowCount > 0) {
                        q.setMaxResults(rowCount);
                    }
                }
            }
            List<Article> list = q.getResultList();
            list.size();

            return list;
        } finally {
            em.close();
        }

    }

    @Override
    public int getApprovedArticleCountByChannelId(Long channelId) {
        EntityManager em = emf.createEntityManager();
        try {
            Query q = em
                    .createQuery("SELECT COUNT(t) FROM Article t WHERE t.channelId = :channelId AND t.status = :status");
            q.setParameter("channelId", channelId);
            q.setParameter("status", ArticleModel.APPROVED);

            return (Integer) q.getSingleResult();
        } finally {
            em.close();
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<Article> findArticles(ArticleFilter filter, int... rowStartIdxAndCount) {
        EntityManager em = emf.createEntityManager();
        try {
            String queryStr = "SELECT FROM Article ORDER BY lastModified desc";
            if (null != filter) {
                queryStr = filter.toQueryString();
            }
            Query q = em.createQuery(queryStr);

            if (null != filter) {
                filter.setParameters(q);

            }

            if (rowStartIdxAndCount != null && rowStartIdxAndCount.length > 0) {
                int rowStartIdx = Math.max(0, rowStartIdxAndCount[0]);
                if (rowStartIdx > 0) {
                    q.setFirstResult(rowStartIdx);
                }
                if (rowStartIdxAndCount.length > 1) {
                    int rowCount = Math.max(0, rowStartIdxAndCount[1]);
                    if (rowCount > 0) {
                        q.setMaxResults(rowCount);
                    }
                }
            }
            List<Article> list = q.getResultList();
            list.size();
            return list;
        } finally {
            em.close();
        }
    }

    @Override
    public int getArticleCount(ArticleFilter filter) {
        EntityManager em = emf.createEntityManager();
        try {
            String queryStr = "SELECT COUNT() FROM Article";
            if (null != filter) {
                queryStr = filter.toCountString();

            }
            Query q = em.createQuery(queryStr);
            if (null != filter) {
                filter.setParameters(q);

            }
            return (Integer) q.getSingleResult();
        } finally {
            em.close();
        }

    }

}
